package cn.chinaflame.pagodas.utils.excel;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.hellojavaer.poi.excel.utils.ExcelProcessController;
import org.hellojavaer.poi.excel.utils.ExcelUtils;
import org.hellojavaer.poi.excel.utils.read.ExcelReadContext;
import org.hellojavaer.poi.excel.utils.read.ExcelReadFieldMapping;
import org.hellojavaer.poi.excel.utils.read.ExcelReadRowProcessor;
import org.hellojavaer.poi.excel.utils.write.ExcelWriteFieldMapping;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import cn.chinaflame.pagodas.utils.Underline2Camel;


public class ExcelWebUtil {
	
	protected static Logger logger = LoggerFactory.getLogger(ExcelWebUtil.class);
	/*@SuppressWarnings("rawtypes")
	public static List<HashMap> getHeadMapList(String excelPath, int columNum, String dataSheetName){
		
		return getHeadMapList(excelTemplate, columNum, dataSheetName);
	}*/
	
	/**
	 * 
	 * @param filePath
	 * @param columNum
	 * @param sheetIndex
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static List<HashMap> getWriteHeadMapList(String filePath, int columNum, int sheetIndex) throws Exception{
		return getWriteHeadMapList(filePath, columNum, sheetIndex, 0);
	}
	
	/**
	 * 
	 * @param filePath
	 * @param columNum
	 * @param sheetIndex
	 * @param headerRow
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static List<HashMap> getWriteHeadMapList(String filePath, int columNum, int sheetIndex, int headerRow) throws Exception{
		InputStream excelIn = new FileInputStream(new File(filePath));
		DefaultExcelReadSheetProcessor<HashMap> sheetProcessor = new DefaultExcelReadSheetProcessor<HashMap>();
        ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping();
        for(int i=0;i<columNum;i++){
        	fieldMapping.put(ExcelUtils.convertColIntIndexToCharIndex(i), ExcelUtils.convertColIntIndexToCharIndex(i));
        }

        sheetProcessor.setSheetIndex(sheetIndex);// required.it can be replaced with 'setSheetName(sheetName)';
        sheetProcessor.setStartRowIndex(headerRow);
        sheetProcessor.setEndRowIndex(headerRow);
        sheetProcessor.setTargetClass(HashMap.class);// required
        sheetProcessor.setFieldMapping(fieldMapping);// required
        sheetProcessor.setTrimSpace(true);
        sheetProcessor.setRowProcessor(new ExcelReadRowProcessor<HashMap>() {
            @Override
            public HashMap process(ExcelProcessController controller, ExcelReadContext<HashMap> context, Row row,
                                   HashMap t) {
                return t;
            }
        });
        ExcelUtils.read(excelIn, sheetProcessor);
		return sheetProcessor.getDataList();
	}
	
	/**
	 * 
	 * @param excelPath
	 * @param columNum
	 * @param dataSheetName
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String, String> getHeadNumMapList(String excelPath, int columNum, String dataSheetName) throws Exception{
		InputStream excelTemplate = ExcelWebUtil.class.getResourceAsStream(excelPath);
		DefaultExcelReadSheetProcessor<LinkedHashMap> sheetProcessor = new DefaultExcelReadSheetProcessor<LinkedHashMap>();
        ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping();
        for(int i=0;i<columNum;i++){
        	fieldMapping.put(ExcelUtils.convertColIntIndexToCharIndex(i), String.valueOf(i));
        }

        sheetProcessor.setSheetName(dataSheetName);// required.it can be replaced with 'setSheetName(sheetName)';
        sheetProcessor.setStartRowIndex(0);
        sheetProcessor.setEndRowIndex(0);
        sheetProcessor.setTargetClass(LinkedHashMap.class);// required
        sheetProcessor.setFieldMapping(fieldMapping);// required
        sheetProcessor.setTrimSpace(true);
        sheetProcessor.setRowProcessor(new ExcelReadRowProcessor<LinkedHashMap>() {
            @Override
            public LinkedHashMap process(ExcelProcessController controller, ExcelReadContext<LinkedHashMap> context, Row row,
            		LinkedHashMap t) {
                return t;
            }
        });
        ExcelUtils.read(excelTemplate, sheetProcessor);
		if(sheetProcessor.getDataList().size()<=0)	throw new Exception("Can not get header information!");
		return sheetProcessor.getDataList().get(0);
	}
	
	/**
	 * 
	 * @param excelPath
	 * @param columNum
	 * @param dataSheetName
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String, String> getHeadMapList(String excelPath, int columNum, String dataSheetName) throws Exception{
		InputStream excelTemplate = ExcelWebUtil.class.getResourceAsStream(excelPath);
		DefaultExcelReadSheetProcessor<HashMap> sheetProcessor = new DefaultExcelReadSheetProcessor<HashMap>();
        ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping();
        for(int i=0;i<columNum;i++){
        	fieldMapping.put(ExcelUtils.convertColIntIndexToCharIndex(i), ExcelUtils.convertColIntIndexToCharIndex(i));
        }
        
        sheetProcessor.setSheetName(dataSheetName);// required.it can be replaced with 'setSheetName(sheetName)';
        sheetProcessor.setStartRowIndex(0);
        sheetProcessor.setEndRowIndex(0);
        sheetProcessor.setTargetClass(HashMap.class);// required
        sheetProcessor.setFieldMapping(fieldMapping);// required
        sheetProcessor.setTrimSpace(true);
        sheetProcessor.setRowProcessor(new ExcelReadRowProcessor<HashMap>() {
            @Override
            public HashMap process(ExcelProcessController controller, ExcelReadContext<HashMap> context, Row row,
                                   HashMap t) {
                return t;
            }
        });
        ExcelUtils.read(excelTemplate, sheetProcessor);
        
        if(sheetProcessor.getDataList().size()<=0)	throw new Exception("Can not get header information!");
		return sheetProcessor.getDataList().get(0);
	}
	
	/**
	 * 
	 * @param headerMap
	 * @param targetObj
	 * @return
	 */
	public static ExcelWriteFieldMapping getWriteDataFieldMapping(Map<String, String> headerMap, Object targetObj){
		List<String> fieldsList = new ArrayList<String>();
		PropertyDescriptor[] propertyDescriptor = BeanUtils.getPropertyDescriptors(targetObj.getClass());
		for(int i=0;i<propertyDescriptor.length;i++){
			fieldsList.add(propertyDescriptor[i].getName());
		}
		
		ExcelWriteFieldMapping fieldMapping = new ExcelWriteFieldMapping();
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
        	String headerName = entry.getValue();
        	if(headerName != null){
	        	headerName =headerName.trim().replace(" ", "_");
	        	headerName = Underline2Camel.underlineToCamel(headerName);
	        	if(fieldsList.contains(headerName)){
	        		fieldMapping.put(entry.getKey(), headerName);
	        	}else{
	        		logger.error("Can not match header " + headerName);
	        	}
        	}
		}
        return fieldMapping;
	}
	
	/**
	 * 
	 * @param headerMap
	 * @param targetObj
	 * @return
	 */
	public static ExcelReadFieldMapping getReadDataFieldMapping(Map<String, String> headerMap, Object targetObj){
		List<String> fieldsList = new ArrayList<String>();
		PropertyDescriptor[] propertyDescriptor = BeanUtils.getPropertyDescriptors(targetObj.getClass());
		for(int i=0;i<propertyDescriptor.length;i++){
			fieldsList.add(propertyDescriptor[i].getName());
		}
		
		ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping();
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
        	String headerName =  entry.getValue() == null ? "": String.valueOf(entry.getValue());
        	if(StringUtils.isNotEmpty(headerName)){
	        	headerName =headerName.trim().replace(" ", "_");
	        	headerName = Underline2Camel.underlineToCamel(headerName);
	        	if(fieldsList.contains(headerName)){
	        		fieldMapping.put(entry.getKey(), headerName);
	        	}else{
	        		logger.error("Can not match header " + headerName);
	        	}
        	}
		}
        return fieldMapping;
	}
	/**
	 * 
	 * @param headerMap
	 * @param targetObj
	 * @return
	 */
	public static ExcelReadFieldMapping getReadDataFieldMapping1(Map<String, String> headerMap, Object targetObj){
		List<String> fieldsList = new ArrayList<String>();
		PropertyDescriptor[] propertyDescriptor = BeanUtils.getPropertyDescriptors(targetObj.getClass());
		for(int i=0;i<propertyDescriptor.length;i++){
			fieldsList.add(propertyDescriptor[i].getName().toUpperCase());
		}
		ExcelReadFieldMapping fieldMapping = new ExcelReadFieldMapping();
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
        	String headerName =  entry.getValue() == null ? "": String.valueOf(entry.getValue());
        	if(StringUtils.isNotEmpty(headerName)){
	        	//headerName =headerName.trim().replace(" ", "_");
	        	//headerName = Underline2Camel.underlineToCamel(headerName);
	        	if(fieldsList.contains(headerName.toUpperCase())){
	        		fieldMapping.put(entry.getKey(), headerName);
	        	}else{
	        		logger.error("Can not match header " + headerName);
	        	}
        	}
		}
        return fieldMapping;
	}
}
